import datetime,math
from jili.price.ta import creat_ta_calcor as ta_frame
from copy import deepcopy
from jili.core.printlog import print
#---------------k线字段
#open,high,low,close,volume
#vwap:均价，pos:剩余仓位，updatetime
#使用dict；考虑场景：
def copydict(t):
    r={}
    for k,v in t.items():
        r[k]=v
    return r
class kline1m:
    def __init__(self,obj,bars_len=2,ktype="0"):
        self.oncallkey=None
        self.obj=obj
        self.iscall=True
        self.bars_len=bars_len
        self.pretimekey=None
        self.endtimes = []
        self.bar={}
        self.bars = []
        self.onbarcall = []
        self.tas=[]
        self.ktype=ktype
        self.starttime=datetime.time(9,30)
        self.endtime0=datetime.time(11,30)
        self.endtime=datetime.time(15,00)
        self.othertime={datetime.time(9,25):(9,31),datetime.time(11,30):(11,30),datetime.time(15,00):(15,0)}
        self.day=None
        self.data_tradetime2=None
        self.check_btimekey=True
        self.isstartday=True
        self.ondata=self.ontick
        #k触发回调规则：1：结束触发，0.实时触发

    def add_ta(self,ta_arg):
        ta0=ta_frame(ta_arg)
        self.tas.append(ta0)
    def __calc_ta(self,bar):
        #print(bar)
        for i in self.tas:
            r = i.onbar(bar)
            #print(r)
            bar.update(r)
        return bar
    def reset(self):
        self.bar={}
        self.bars = []
    def setonbar(self,call):
        self.onbarcall.append(call)

    def ontick(self,t):
        if "obj" in t.keys():
            self.obj=t["obj"]
        timekey0=t["timekey"]
        vv="volume"
        if t[vv] == 0:
            return {}
        if not self.checktime(timekey0):
            return {}

        isend,btimekey=self.getbartimekey(timekey0)
        p=t["lastPrice"]
        if self.bars:
            bar=self.bars[-1]
            if btimekey==bar["timekey"]:
                if bar["high"]<p:
                    bar["high"] = p
                    bar["hightime"] = timekey0
                elif bar["low"] > p:
                    bar["low"] = p
                    bar["lowtime"] = timekey0
                bar["close"]=p
                bar["volume"]=bar["volume"]+t["volume"]
                if "vwap" in t.keys():
                    bar["vwap"]=t["vwap"]
                bar["uptime"]=timekey0
                if self.ktype== "1":
                    if isend:
                        self.__calc_ta(bar)
                        for i in self.onbarcall:
                            i(self.bar)
                elif self.ktype== "0":
                    self.__calc_ta(bar)
                    for i in self.onbarcall:
                        i(self.bar)
            else:
                bar0 = {}
                bar0["timekey"] = btimekey
                bar0["obj"] = self.obj
                if "code" in t.keys():
                    bar0["code"] = t["code"]
                bar0["open"] = p
                bar0["high"] = p
                bar0["low"] = p
                bar0["close"] = p
                bar0["volume"] = t["volume"]
                if "vwap" in t.keys():
                    bar0["vwap"] = t["vwap"]
                bar0["uptime"] = timekey0
                bar0["hightime"] = timekey0
                bar0["lowtime"] = timekey0
                bar0["opentime"] = timekey0
                self.bars.append(bar0)
                if len(self.bars) > self.bars_len:
                    self.bars.pop(0)
                self.bar = bar0
                if self.ktype == "0":
                    self.__calc_ta(self.bar)
                    for i in self.onbarcall:
                        i(self.bar)
        else:
            bar0={}
            bar0["timekey"]=btimekey
            bar0["obj"]=self.obj
            if "code" in t.keys():
                bar0["code"]=t["code"]
            bar0["open"]=p
            bar0["high"]=p
            bar0["low"]=p
            bar0["close"]=p
            bar0["volume"]=t["volume"]
            if "vwap" in t.keys():
                bar0["vwap"] = t["vwap"]
            else:
                bar0["vwap"] = 0
            bar0["uptime"]=timekey0
            bar0["hightime"] = timekey0
            bar0["lowtime"] = timekey0
            bar0["opentime"] = timekey0
            self.bars.append(bar0)
            self.bar=bar0
            if self.ktype == "0":
                self.__calc_ta(self.bar)
                for i in self.onbarcall:
                    i(self.bar)
        return self.bar
    def getbartimekey(self,a):
        t0=datetime.time(a.hour,a.minute)
        if t0 in self.othertime.keys():
            tt=self.othertime[t0]
            b=datetime.datetime(a.year, a.month, a.day, tt[0], tt[1])
            # self.pretimekey = b
            return False,b
        else:
            b = datetime.datetime(a.year, a.month, a.day, a.hour, a.minute)
            if b==self.pretimekey:
                b0 = b + datetime.timedelta(minutes=1)
                self.pretimekey= b0
                return True,b
            else:
                b=b+datetime.timedelta(minutes=1)
                if self.pretimekey is None:
                    self.pretimekey= b
                return False,b
    def checktime(self,a):
        r=a.time()<=self.endtime
        return r
class klinenm:
    def __init__(self,obj,period=5,bars_len=2,bar0=None):#1:按根数算
        self.obj=obj
        self.period=period
        self.endtime = datetime.time(15, 00)
        if period>30:
            self.tk_keys=self.calc_tk_keys(period)
            self.nowtime=self.tk_keys[0]
            self.getbartimekey=self.getbartimekey1
        else:
            self.getbartimekey=self.getbartimekey0
        self.bar={}
        if bar0 is None:
            self.bars=[]
        else:
            self.bars=[bar0]
        self.bars_len=bars_len
        self.onbarcall = []
        self.tas = []
        self.day=None
        self.data_tradetime2=None
        self.ondata = self.onbar
        self.pretimekey=None
    def calc_tk_keys(self,period):
        tk_keys=[]
        n0 = 120 / period
        n4 = math.ceil(n0)
        delta0 = 120 % period
        if delta0 == 0:
            delta1 = 0
        else:
            delta1 = period - delta0
        n2 = 240 / period
        n3=math.ceil(n2)
        d=datetime.datetime.now()
        d0=datetime.datetime(d.year,d.month,d.day,9,30)
        d01 = datetime.datetime(d.year, d.month, d.day, 13,0)+ datetime.timedelta(minutes=delta1)
        for i in range(int(n3)):
            i=i+1
            if delta0==0:
                if i<=n0:
                    d1=d0+datetime.timedelta(minutes=i*period)
                    tk_keys.append(d1.time())
                elif i==n3:
                    tk_keys.append(datetime.time(15,0))
                else:
                    d1 = d01 + datetime.timedelta(minutes=(i-n4) * period)
                    tk_keys.append(d1.time())
            else:
                if i<=n0:
                    d1=d0+datetime.timedelta(minutes=i*period)
                    tk_keys.append(d1.time())
                elif i==n4:
                    tk_keys.append(d01.time())
                elif i==n3:
                    tk_keys.append(datetime.time(15,0))
                else:
                    d1 = d01 + datetime.timedelta(minutes=(i-n4) * period)
                    tk_keys.append(d1.time())
        return tk_keys
    def add_ta(self, ta_arg):
        ta0 = ta_frame(ta_arg)
        self.tas.append(ta0)

    def __calc_ta(self, bar):
        for i in self.tas:
            r = i.onbar(bar)
            bar.update(r)
        return bar
    def setonbar(self,call):
        self.onbarcall.append(call)
    def getbartimekey0(self,timekey):
        if timekey.minute%self.period==0:
            d= datetime.datetime(timekey.year,timekey.month,timekey.day,timekey.hour,timekey.minute)
        else:
            r=(int(timekey.minute/self.period)+1)*self.period
            d= datetime.datetime(timekey.year,timekey.month,timekey.day,timekey.hour)+datetime.timedelta(minutes=r)
        if d==timekey:
            return True,d
        else:
            return False,d
    def getbartimekey1(self,timekey):
        time=timekey.time()
        isend=False
        d=None
        for tt in self.tk_keys:
            if time<=tt:
                d = datetime.datetime(timekey.year, timekey.month, timekey.day, tt.hour, tt.minute)
                if time == tt:
                    isend = True
                break
        # if d is None:
            # print(timekey,self.tk_keys)
        return isend,d
    def onbar(self,t):
        if "obj" in t.keys():
            self.obj=t["obj"]
        timekey0 = t["timekey"]
        if timekey0.time() > self.endtime:
            return None
        isend,timekey=self.getbartimekey(timekey0)
        if self.bars:
            bar0=self.bars[-1]
            if timekey==bar0["timekey"]:
                if bar0["high"]<t["high"]:
                    bar0["high"]=t["high"]
                elif bar0["low"] > t["low"]:
                    bar0["low"] = t["low"]
                bar0["close"]=t["close"]
                bar0["volume"]=bar0["volume"]+t["volume"]
                bar0=self.__calc_ta(bar0)
                self.bar = bar0
            else:
                bar0={}
                bar0["timekey"]=timekey
                bar0["obj"]=self.obj
                if "code" in t.keys():
                    bar0["code"] = t["code"]
                bar0["open"]=t["open"]
                bar0["high"]=t["high"]
                bar0["low"]=t["low"]
                bar0["close"]=t["close"]
                bar0["volume"]=t["volume"]
                bar0=self.__calc_ta(bar0)
                self.bars.append(bar0)
                self.bar=bar0
        else:
            bar0={}
            bar0["timekey"]=timekey
            bar0["obj"]=self.obj
            if "code" in t.keys():
                bar0["code"]=t["code"]
            bar0["open"]=t["open"]
            bar0["high"]=t["high"]
            bar0["low"]=t["low"]
            bar0["close"]=t["close"]
            bar0["volume"]=t["volume"]
            bar0=self.__calc_ta(bar0)
            self.bars.append(bar0)
            self.bar=bar0

        if isend:
            for i in self.onbarcall:
                i(self.bar)
        return self.bar
if __name__=="__main__":
    knm=klinenm("000001",45)